using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;
using GMID = System.Int64;

namespace Cobalt75.GreyMatter
{
    public enum GMRelationCaching
    {
        Snapshot,//Gets all the items once, locks them as a historical snapshot.
        Lazy,//Gets all ids first then items as required, but after they've been got, doesn't bother to update.
        Updating//Gets items as required, then re-gets the item as it's updated
        //If something is deleted then the count/etc changes!
        //Every change causes the ID list to be re-updated.

    }
    public class GMRelation<T> : IGMRelation
        where T : GMTable
    {
        GMTable pParentObject;
        public GMRelation(GMTable parentObject) {
            pParentObject = parentObject;
        }
        
        GMID RelationID;
        T pCache;
        Int64 pCacheTicks;
        GMRelationCaching _Caching = GMRelationCaching.Updating;
        public GMRelationCaching Caching
        {
            get
            {
                return (_Caching);
            }
            set
            {
                if (value == GMRelationCaching.Snapshot)
                {
                    throw (new GMException("Singluar relations cannot have snapshots"));
                }
                _Caching = value;

                pCache = null;
            }
        }
        public void Refresh()
        {
            pCache = null;
        }
        public T Value
        {
            get
            {
                if (RelationID == 0)
                {
                    return (null);
                }
                if (_Caching == GMRelationCaching.Updating)
                {
                    if (IsOutdated)
                    {
                        pCache = pParentObject.Communicator.SelectFromId<T>(RelationID,true);
                    }
                    pCacheTicks = pParentObject.Communicator.GetTableSync(typeof(T));
                    
                    return (pCache);
                }
                else
                {
                    if (pCache == null)
                    {
                        pCache = pParentObject.Communicator.SelectFromId<T>(RelationID,true);
                    }
                    return (pCache);
                }
            }
            set
            {
                RelationID = value.Id;
                pParentObject.Changed();
            }
        }
        public bool IsOutdated
        {
            get
            {
                if (pCache == null)
                {
                    return (true);
                }
                if (pParentObject.Communicator.GetTableSync(typeof(T)) > pCacheTicks)
                {
                    return (true);
                }
                return (false);
            }
        }
        
        public GMID Id
        {
            get
            {
                return RelationID;
            }
            set
            {
                pCache = null;
                RelationID = value;
            }
        }
        public static implicit operator GMTable(GMRelation<T> relation)
        {
            return (relation.Value);
        }
        public static implicit operator T(GMRelation<T> relation)
        {
            return (relation.Value);
        }
        public static GMTable ToGMTable(GMRelation<T> relation)
        {
            return (relation.Value);
        }
        public GMTable ToGMTable()
        {
            return (Value);
        }
    }


    
   
   
    
}